//! @Author: DengLibin
//! @Date: Create in 2025-02-07 10:51:39
//! @Description: mysql表数据导出到sqlite

use log::info;
use serde::Serialize;
use sqlx::{mysql::MySqlRow, FromRow};

use crate::sys::global::GlobalResult;
use my_trait::{MustHaveFieldType, MustHaveTableName, Struct2Map};

use super::mysql::mysql_dao;
use super::sqlite::sqlite_dao;

/// @Author: DengLibin
/// @Date: Create in 2025-02-07 10:55:36
/// @mysql_url: mysql 连接地址
/// @sqlite_db: db文件路径
/// @table_name: 表名
/// @create_table_sql: db建表语句
/// @colums: 字段
/// @up_column: 增量字段是第几个（0开始） 数字类型 按批次导出
pub async fn mysql2sqlite<E>(
    mysql_url: &str,
    sqlite_db: &str,
    table_name: &str,
    create_table_sql: &str,
    columns: Vec<String>,
    up_column_index: usize,
) -> GlobalResult<()>
where
    E: MustHaveTableName
        + MustHaveFieldType
        + Struct2Map
        + Serialize
        + Send
        + Unpin
        + for<'r> FromRow<'r, MySqlRow>,
{
    let mysql_conn_pool = mysql_dao::get_conn_pool(mysql_url, 1).await?;
    let sqlite_conn_pool: sqlx::Pool<sqlx::Sqlite> = sqlite_dao::get_conn_pool(sqlite_db).await?;

    sqlite_dao::create_tabale(create_table_sql, &sqlite_conn_pool).await?;

    let colums_str = columns.join(",");
    let mut start_value: i64 = 0;
    let up_column = columns.get(up_column_index).unwrap();
    let mut count = 0;
    loop {
        let sql = format!(
            "select {} from {} where {} > {} order by {} limit 1000",
            colums_str, table_name, up_column, start_value, up_column
        );
        log::info!("sql:{}", sql);
        let rows = mysql_dao::query_sql::<E>(&sql, &mysql_conn_pool).await?;
        if rows.is_empty() {
            break;
        }
        count += rows.len();
        start_value = rows
            .last()
            .unwrap()
            .to_map()
            .get(up_column)
            .unwrap()
            .to_string()
            .parse()
            .unwrap();

        sqlite_dao::insert_batch::<E>(&rows, &sqlite_conn_pool).await?;
        info!("进度:{}", count);
        // if count > 500_0000 {
        //     break;
        // }
    }

    Ok(())
}
